package net.expectx.pay.gateway.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import io.swagger.annotations.ApiOperation;
import net.expectx.common.single.util.RequestUtil;
import net.expectx.pay.core.api.PaymentHandlerInterface;
import net.expectx.pay.core.service.provider.ProviderWXPayAppletDriver;
import net.expectx.pay.core.service.provider.ProviderWXPayPublicNumberDriver;
import net.expectx.pay.gateway.common.AdminConstants;
import net.expectx.pay.gateway.common.AdminResult;
import net.expectx.pay.gateway.common.util.ExpectXUtil;
import net.expectx.pay.gateway.common.util.RedisUtil;
import net.expectx.pay.gateway.dao.bean.*;
import net.expectx.pay.gateway.rpc.api.MerchantPaymentConfigService;
import net.expectx.pay.gateway.rpc.api.PaymentChannelService;
import net.expectx.pay.gateway.rpc.api.ProductOrderHeaderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lijian
 */
@Controller
@RequestMapping("/pay/")
public class WXPayController {
    @Autowired
    private ProductOrderHeaderService productOrderHeaderService;
    @Autowired
    private MerchantPaymentConfigService merchantPaymentConfigService;
    @Autowired
    private PaymentChannelService paymentChannelService;



    @ApiOperation(value = "微信发起支付")
    @RequestMapping(value = "wxpay", method = RequestMethod.POST)
    @ResponseBody
    public Object wxpay(HttpServletRequest request) {
        try {
            PaymentHandlerInterface paymentHandlerInterface = null;
            Map<String, String> params = Maps.newHashMapWithExpectedSize(7);
            String openId = request.getParameter("openId");
            params.put("openId", openId);

            /**
             * 检验参数
             */
            AdminResult adminResult = calibrationParameters(request, params);
            if (!adminResult.isSuccess()) {
                return adminResult;
            }
            Map result = (Map) adminResult.getData();
            MerchantPaymentConfig merchantPaymentConfig = (MerchantPaymentConfig) result.get("merchantPaymentConfig");
            PaymentChannel paymentChannel = (PaymentChannel) result.get("paymentChannel");
            Map<String, String> data = (Map<String, String>) result.get("body");

            adminResult = new AdminResult(productOrderHeaderService.createOrder(data));
            if (!adminResult.isSuccess()) {
                return adminResult;
            }
            ProductOrderHeader productOrderHeader = (ProductOrderHeader) adminResult.getData();
            Jedis jedis= RedisUtil.getJedis();
            jedis.hset("EXPAY:productOrder",productOrderHeader.getOrderId(), JSONObject.toJSONString(productOrderHeader));
            jedis.close();
            Map<String, Object> payParams = Maps.newHashMapWithExpectedSize(7);
            switch (paymentChannel.getChannelAttr()) {
                case "wx_lite":
                    //小程序
                    paymentHandlerInterface = new ProviderWXPayAppletDriver();
                    payParams.put("subAppId", merchantPaymentConfig.getAppId());
                    payParams.put("subMchId", merchantPaymentConfig.getMchId());
                    payParams.put("notifyUrl",  AdminConstants.WEI_XIN_PAY_NOTIFY);
                    payParams.put("body", productOrderHeader.getOrderName());
                    payParams.put("outTradeNo", productOrderHeader.getOrderId());
                    payParams.put("totalFee", productOrderHeader.getGrandTotal().toString());
                    payParams.put("createIp", RequestUtil.getIpAddr(request));
                    payParams.put("subOpenId", openId);
                    payParams.put("orderId", productOrderHeader.getMerchantOrderId());
                    adminResult = new AdminResult(paymentHandlerInterface.doPay(payParams));
                    break;
                case "wx_pub":
                    //小程序
                    paymentHandlerInterface = new ProviderWXPayPublicNumberDriver();
                    payParams.put("subAppId", merchantPaymentConfig.getAppId());
                    payParams.put("subMchId", merchantPaymentConfig.getMchId());
                    payParams.put("notifyUrl",  AdminConstants.WEI_XIN_PAY_NOTIFY);
                    payParams.put("body", productOrderHeader.getOrderName());
                    payParams.put("outTradeNo", productOrderHeader.getOrderId());
                    payParams.put("totalFee", productOrderHeader.getGrandTotal().toString());
                    payParams.put("createIp", RequestUtil.getIpAddr(request));
                    payParams.put("subOpenId", openId);
                    payParams.put("orderId", productOrderHeader.getMerchantOrderId());
                    adminResult = new AdminResult(paymentHandlerInterface.doPay(payParams));
                    break;
                default:
                    adminResult = new AdminResult(false, 0, "不支持的支付方式", null);

            }
            return adminResult;
        } catch (Exception e) {
            e.printStackTrace();
            return new AdminResult(false, 0, "系统错误", null);
        }
    }



    public AdminResult calibrationParameters(HttpServletRequest request, Map<String, String> params) {
        try {
            AdminResult adminResult= ExpectXUtil.encrypt(request);
            if (!adminResult.isSuccess()){
                return  adminResult;
            }
            /*商户号*/
            String merchantNo = request.getParameter("merchantNo");
            /*应用号*/
            String applicationNo = request.getParameter("applicationNo");
            /*通道属性*/
            String channel = request.getParameter("channel");
            String merchantOrderId = request.getParameter("merchantOrderId");
            String orderName = request.getParameter("orderName");
            String orderDesc = request.getParameter("orderDesc");
            Long orderDate = Long.parseLong(request.getParameter("orderDate"));
            String tradeAmount = request.getParameter("tradeAmount");
            String sign = request.getParameter("sign");

            /**
             * 检验支付通道
             */
            PaymentChannelExample paymentChannelExample = new PaymentChannelExample();
            paymentChannelExample.createCriteria().andChannelAttrEqualTo(channel);
            List<PaymentChannel> paymentChannels = paymentChannelService.selectByExample(paymentChannelExample);
            if (paymentChannels.isEmpty()) {
                adminResult = new AdminResult(false, 0, "支付通道参数错误", null);
                return adminResult;
            }
            PaymentChannel paymentChannel = paymentChannels.get(0);

            /**
             * 检验支付通道配置
             */
            MerchantPaymentConfigExample merchantPaymentConfigExample = new MerchantPaymentConfigExample();
            merchantPaymentConfigExample.createCriteria()
                    .andMerchantNoEqualTo(merchantNo)
                    .andApplicationNoEqualTo(applicationNo)
                    .andPaymentChannelEqualTo(paymentChannel.getId());
            List<MerchantPaymentConfig> merchantPaymentConfigs = merchantPaymentConfigService.selectByExample(merchantPaymentConfigExample);
            if (merchantPaymentConfigs.isEmpty()) {
                adminResult = new AdminResult(false, 0, "商户号或应用号错误或" + paymentChannel.getName() + "未开通", null);
                return adminResult;
            }
            MerchantPaymentConfig merchantPaymentConfig = merchantPaymentConfigs.get(0);

            MerchantUser merchantUser = merchantPaymentConfig.getMerchantUser();

            String notifyUrl = merchantPaymentConfig.getNotifyUrl();
            String returnUrl = merchantPaymentConfig.getReturnUrl();


            String currencyUom = "CNY";


            /**
             * 校验密钥
             */
            String privateKey = merchantUser.getPrivateKey();


            /**
             * 校验签名
             */
            Map<String, String> body = new HashMap<>(2);
            body.put("merchantNo", merchantNo);
            body.put("applicationNo", applicationNo);
            body.put("channel", channel);
            body.put("merchantOrderId", merchantOrderId);
            body.put("orderName", orderName);
            body.put("orderDesc", orderDesc);
            body.put("orderDate", orderDate.toString());
            body.put("tradeAmount", tradeAmount);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                body.put(entry.getKey(), entry.getValue());
            }

            String s = WXPayUtil.generateSignature(body, privateKey, WXPayConstants.SignType.MD5);
            System.out.println("签名：" + s);
            System.out.println("获得签名：" + sign);

            if (!s.equals(sign)) {
                adminResult = new AdminResult(false, 0, "签名验证失败", null);
                return adminResult;
            }
            Map result = Maps.newHashMapWithExpectedSize(7);
            result.put("merchantPaymentConfig", merchantPaymentConfig);
            result.put("paymentChannel", paymentChannel);
            result.put("merchantUser", merchantUser);

            body.put("notifyUrl", notifyUrl);
            body.put("channel", paymentChannel.getId() + "");
            body.put("currencyUom", currencyUom);
            result.put("body", body);

            adminResult = new AdminResult(true, 200, "成功", result);
            return adminResult;
        } catch (Exception e) {
            e.getLocalizedMessage();
            AdminResult adminResult = new AdminResult(false, 0, "系统错误或缺少参数", null);
            return adminResult;
        }

    }




}
